﻿#pragma once

#include <vulkan/vulkan.hpp>
#include "Render/Scene/PreRenderSceneNodes.h"
#include "Render/Scene/Frustum.h"
#include "Render/Scene/SceneParametersBuffer.h"
#include "Render/Scene/DefferRenderAttachments.h"

class CVulkanScene;

class CVulkanViewportWidget;
class CVulkanScene;

//平行光
class CVulkanDirectionalLight
{
public:
    CVulkanDirectionalLight();
    ~CVulkanDirectionalLight();

    void SetData(const SPreRenderDirectionalLight& InLightData);

    //记录生成聚光灯阴影图的命令
    void RecordShadowMapCommand(
        vk::CommandBuffer InCmdBuffers
        ,CVulkanScene* InScene
        ,const SFrustumPoints & InFrustumPoints
        ,float Near
        ,float Far
        );

    //记录延迟着色的命令
    void RecordDefferShadingCommand(
        vk::CommandBuffer InCmdBuffers
        ,CVulkanScene* InScene
        ,const SSceneParameters& InParameters 
        ,CDefferRenderAttachments* Attachments
        );

    int32_t LightIndex=-1;
protected:
    SPreRenderDirectionalLight LightData;


    //use cascade shadow map
    TVector<std::shared_ptr<CGPURenderTarget>> CascadeShadowMaps;
    TVector<vk::Framebuffer> CascadeShadowMapFrameBuffers;
    TVector<SMatrix4x4> ProjectViewMatrixs;
    TVector<float> CascadeMaxDepths;

    //deffer shading 
    vk::DescriptorSet DescriptorSet=nullptr;
    std::shared_ptr<TVulkanUniformBuffer<SDirectionalLightDefferShadingFragmentUniformBuffer>> DefferShadingUniformBuffer;


};

//管理平行光
class CVulkanDirectionalLights
{
public:
    // CVulkanDirectionalLights();
    // ~CVulkanDirectionalLights();

    void PreProcess(
        const TVector<SPreRenderDirectionalLight>& InLightData
        ,CVulkanViewportWidget* InViewport
        ,CVulkanScene* InScene
        );

    //记录生成聚光灯阴影图的命令
    void RecordShadowMapCommand(
        vk::CommandBuffer InCmdBuffers
        ,CVulkanScene* InScene
        ,const SFrustumPoints & InFrustumPoints,float Near,float Far
        );

    //记录延迟着色的命令
    void RecordDefferShadingCommand(
        vk::CommandBuffer InCmdBuffers
        ,CVulkanScene* InScene
        ,const SSceneParameters& InParameters 
        ,CDefferRenderAttachments* Attachments
        
        );

    int64_t GetDirectionalLightNum() const;

    //测试一个球体是否在光照范围内
    bool IsInLightRange(int64_t InLightIndex,const SVec3& InSpherePosition,float InSphereRadius);
protected:

    //所有平行光数据
    TVector<SPreRenderDirectionalLight> LightDatas;

    //所有平行光
    TVector<CVulkanDirectionalLight> DirectionalLights;

};
